import { Logger } from "./Logger";

const { ccclass, property } = cc._decorator;

@ccclass
export default class Uint8ArrayHelper {

    public static intToUint8Array(value: number): Uint8Array {
        let arrayBuffer: ArrayBuffer = new ArrayBuffer(4);
        let view: DataView = new DataView(arrayBuffer);
        view.setInt32(0, value, true);
        let res: Uint8Array = new Uint8Array(arrayBuffer);
        return res;
    }

    public static boolToUint8Array(value: boolean) {
        let arrayBuffer: ArrayBuffer = new ArrayBuffer(1);
        let view: DataView = new DataView(arrayBuffer);
        if (value) {
            view.setInt8(0, 1);
        } else {
            view.setInt8(0, 0);
        }
        let res: Uint8Array = new Uint8Array(arrayBuffer);
        return res;
    }


    public static floatToUint8Array(value: number): Uint8Array {
        let arrayBuffer: ArrayBuffer = new ArrayBuffer(4);
        let view: DataView = new DataView(arrayBuffer);
        view.setFloat32(0, value, true);
        let res: Uint8Array = new Uint8Array(arrayBuffer);
        return res;
    }

    public static doubleToUint8Array(value: number): Uint8Array {
        let arrayBuffer: ArrayBuffer = new ArrayBuffer(8);
        let view: DataView = new DataView(arrayBuffer);
        view.setFloat64(0, value, true);
        let res: Uint8Array = new Uint8Array(arrayBuffer);
        return res;
    }

    public static uint8ArrayToInt(value: Uint8Array): number {
        let res = new Uint32Array(1)
        res[0] = (value[3] & 0xFF) << 24;
        res[0] = res[0] | ((value[2] & 0xFF) << 16)
        res[0] = res[0] | ((value[1] & 0xFF) << 8)
        res[0] = res[0] | (value[0] & 0xFF)
        return res[0]
    }

    public static uint8ArrayToBool(value: Uint8Array): boolean {
        let temp: number = this.uint8ArrayToInt(value);
        if (temp == 1) {
            return true;
        }
        return false;
    }


    public static arrayBufferToFloat(dataArrayBuffer: ArrayBuffer) {
        let view = new DataView(dataArrayBuffer);
        return view.getFloat32(0, true);
    }

    public static arrayBufferToDouble(dataArrayBuffer: ArrayBuffer) {
        let view = new DataView(dataArrayBuffer);
        return view.getFloat64(0, true);
    }


    public static uint8ArrayToString(array: Uint8Array): string {
        let tempStr: string = "";
        for (let i = 0; i < array.length;) {
            let tempCharCode: number = this.uint8ArrayToInt(array.subarray(i, i + 2));
            let tempchar: string = String.fromCharCode(tempCharCode);
            if (tempCharCode != 0) {
                tempStr += tempchar;
            }
            i += 2;
        }
        Logger.log("uint8ArrayToString==", tempStr)
        return tempStr;

        // var dataString = "";
        // for (var i = 0; i < array.length; i++) {
        //   dataString += String.fromCharCode(array[i]);
        // }

        // return dataString
    }

    public static uint8arrayToBase64(bytes: Uint8Array): string {
        //从本地读取文件到unit8Array
        var base64 = '';
        var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        var byteLength = bytes.byteLength;
        var byteRemainder = byteLength % 3;
        var mainLength = byteLength - byteRemainder;
        var a, b, c, d;
        var chunk;
        // Main loop deals with bytes in chunks of 3
        for (var i = 0; i < mainLength; i = i + 3) {
            // Combine the three bytes into a single integer
            chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
            // Use bitmasks to extract 6-bit segments from the triplet
            a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
            b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
            c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
            d = chunk & 63; // 63 = 2^6 - 1
            // Convert the raw binary segments to the appropriate ASCII encoding
            base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
        }
        // Deal with the remaining bytes and padding
        if (byteRemainder == 1) {
            chunk = bytes[mainLength];
            a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2;
            // Set the 4 least significant bits to zero
            b = (chunk & 3) << 4 // 3 = 2^2 - 1;
            base64 += encodings[a] + encodings[b] + '==';
        }
        else if (byteRemainder == 2) {
            chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
            a = (chunk & 16128) >> 8 // 16128 = (2^6 - 1) << 8;
            b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4;
            // Set the 2 least significant bits to zero
            c = (chunk & 15) << 2 // 15 = 2^4 - 1;
            base64 += encodings[a] + encodings[b] + encodings[c] + '=';
        }
        return "data:image/jpeg;base64," + base64;
    }



    public static isEmojiCharacter(checkStr: string) {
        if (checkStr.length > 0) {
            for (let i = 0; i < checkStr.length; i++) {
                let code: number = checkStr.charCodeAt(i)
                if (code >= 0xd800 && code <= 0xdbff) {
                    if (i < checkStr.length - 1) {
                        let code2: number = checkStr.charCodeAt(i + 1)
                        let uc: number = ((code - 0xd800) * 0x400) + (code2 - 0xdc00) + 0x10000;
                        if (uc >= 0x1d000 && uc <= 0x1f77f) {
                            return true;
                        }
                    }
                }
                else if (checkStr.length > 1) {
                    let code2: number = checkStr.charCodeAt(i + 1)
                    if (code2 == 0x20e3) {
                        return true
                    }
                }
                else {
                    if (code >= 0x2100 && code <= 0x27ff) {
                        return true
                    }
                    else if (code >= 0x2B05 && code <= 0x2b07) {
                        return true
                    }
                    else if (code >= 0x2934 && code <= 0x2935) {
                        return true
                    }
                    else if (code >= 0x3297 && code <= 0x3299) {
                        return true
                    }
                    else if (code == 0xa9 || code == 0xae || code == 0x303d || code == 0x2b55
                        || code == 0x2b1c || code == 0x2b1b || code == 0x2b50) {
                        return true
                    }
                }
            }

        }
    }

    //随机个数的汉字
    public static randomChinese(num: number): string {
        let words: string = ""
        for (let i = 0; i < num; i++) {
            // const unicodeStr: string = String.fromCharCode(Math.round(Math.random() * 20901) + 19968);
            const unicodeStr: string = String.fromCharCode(Math.round(Math.random() * 1000) + 19968);
            words += unicodeStr
        }
        return words
    }


}